import nodeFetch, {RequestInit, BodyInit} from 'node-fetch';
import {FetchResponse} from './fetch2';
import {sourceMap} from './apiPathTranslator';

export enum ContendType {
    json = 'application/json',
    formData = 'multipart/form-data',
}

export enum Credentials {
    omit = 'omit',
    sameOrigin = 'same-origin:',
    include = 'include',
}

interface FetchOptions extends RequestInit {
    credentials?: Credentials;
}

function fromPairs(pairs: any) {
    const result: any = {};
    if (pairs == null) {
        return result;
    }
    for (const pair of pairs) {
        console.error(pair);
        result[pair[0]] = pair[1];
    }
    return result;
}

function fetch(url: string, options: RequestInit): Promise<FetchResponse> {
    return nodeFetch(url, options);
}

function createOption(method: string, options: FetchOptions) {
    const {body, credentials, headers} = options;
    return {
        method,
        headers: headers || {
            'Content-Type': ContendType.json,
        },
        credentials: credentials || Credentials.include,
        ...(method !== 'GET' ? {
            body,
        } : {}),
    };
}

async function createConnection(method: string, url: string, options: FetchOptions) {
    const res = await fetch(url, createOption(method, options));
    if (!res.ok) {
        return {success: false, ...res};
    }
    return res.json();
}

class CreateServer {

    private readonly serverName: string;

    constructor(serverName: string) {
        this.serverName = serverName;
    }

    public get() {
        return this.create.bind(this, 'GET');
    }

    public post() {
        return this.create.bind(this, 'POST');
    }

    private getUrl(path: string, parameter: string[]): string {
        return `${this.serverName}/${path}${parameter?.map((value) => `/${value}`).join('') || ''}`;
    }

    private create(method: string, path: string, parameter: string[], body: BodyInit) {
        return createConnection(method, this.getUrl(path, parameter), {body});
    }
}

const init = fromPairs(Object.keys(sourceMap).map((s) => ([s, new CreateServer(`<${s}>`)])));

export default init;
